#include <fstream>
#include "../scene_main.h"
#include "game.h"
#include "object_screen.h"
#include "object_world.h"
#include "actor.h"
#include "player.h"
#include "../affiliate/sprite.h"


void Game::init(std::string title, int width, int height)
{
    screen_size_ = glm::vec2(width, height);

    // SDL3 初始化
    if(!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,"SDL_Init Error! %s\n", SDL_GetError());
        // return 0;
    }

    // SDL3_Mixer 初始化
    if (Mix_Init(MIX_INIT_MP3 | MIX_INIT_OGG | MIX_INIT_MID) != (MIX_INIT_MP3 | MIX_INIT_OGG | MIX_INIT_MID)) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_Mix_Init Error! %s\n", SDL_GetError());
    }
    if(!Mix_OpenAudio(0, NULL)) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_Mix_OpenAudio Error! %s\n", SDL_GetError());
        // return 0;
    }
    Mix_AllocateChannels(16);   // 分配16个音频通道
    Mix_VolumeMusic(MIX_MAX_VOLUME / 4);    // 设置音乐音量
    Mix_Volume(-1, MIX_MAX_VOLUME / 4);     // 设置音效音量

    /*
    window = SDL_CreateWindow("SDL Tutorial", screen_size_.x, screen_size_.y, 0);
    if(window == nullptr) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_CreateWindow Error! %s\n", SDL_GetError());
        // return 0;
    }
    renderer = SDL_CreateRenderer(window, NULL);
    if(window == nullptr) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_CreateRenderer Error! %s\n", SDL_GetError());
        // return 0;
    } */

    // SDL3_TTF Initialeze
    if(!TTF_Init()) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_TTF Initialize Failed:%s\n", SDL_GetError());
    }
    // 创建窗口与渲染器
    SDL_CreateWindowAndRenderer(title.c_str(), width, height, SDL_WINDOW_RESIZABLE, &window, &renderer);
    if(!window || !renderer){
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Create window or renderer fail:%s\n", SDL_GetError());
    }
    // 设置窗口逻辑分辨率
    SDL_SetRenderLogicalPresentation(renderer, width, height, SDL_LOGICAL_PRESENTATION_LETTERBOX);

    // 计算帧间隔
    frameDelay = 1000000000 / FPS;

    // 创建资源管理器
    asset_store_ = new AssetStore(renderer);
    
    // 创建场景
    current_scene_ = new SceneMain();
    current_scene_->init();
}

void Game::run()
{
    while(is_running_) {
        auto start = SDL_GetTicksNS();
        handleEvents();
        update(dt);
        render();
        auto end = SDL_GetTicksNS();
        auto elapsed = end - start;
        if(elapsed < frameDelay) {
            SDL_DelayNS(frameDelay-elapsed);
            dt = frameDelay / 1.0e9;
        } else {
            dt = elapsed / 1.0e9;
        }
        // SDL_Log("FPS:%f", 1.0/dt);
    }
}

void Game::handleEvents()
{
    SDL_Event event;
    while(SDL_PollEvent(&event)) {
        switch (event.type)
        {
        case SDL_EVENT_QUIT: {
            is_running_ = false;
            break;
        }

        default:{
            current_scene_->handleEvents(event);
        }
        }
    }
}

void Game::update(float dt)
{
    updateMouse();
    current_scene_->update(dt);
}

void Game::render()
{
    SDL_SetRenderDrawColor(renderer, 0,0,0, 255);
    SDL_RenderClear(renderer);
    current_scene_->render();
    SDL_RenderPresent(renderer);
}

void Game::clean()
{
    if (current_scene_) {
        current_scene_->clean();
        delete current_scene_;
    }
    if (asset_store_) {
        asset_store_->clean();
        delete asset_store_;
    }
    // 释放渲染器和窗口
    if (ttf_engine) {
        TTF_DestroyRendererTextEngine(ttf_engine);
    }
    if (renderer) {
        SDL_DestroyRenderer(renderer);
    }
    if (window) {
        SDL_DestroyWindow(window);
    }
    // 推出 Mix
    Mix_CloseAudio();
    Mix_Quit();
    // 推出 TTF
    TTF_Quit();
    // 推出 SDL
    SDL_Quit();
}

void Game::setScore(int score)
{
    score_ = score;
    if (score_ > high_score_) {
        high_score_ = score_;
    }
}

void Game::addScore(int score)
{
    setScore(score_ + score);
}

void Game::changeScene(Scene *scene)
{
    if (current_scene_) {
        current_scene_->clean();
        delete current_scene_;
    }
    current_scene_ = scene;
    current_scene_->init();
}

TTF_Text *Game::createTTF_Text(const std::string &text, const std::string &font_path, int font_size)
{
    auto font = asset_store_->getFont(font_path, font_size);
    return TTF_CreateText(ttf_engine, font, text.c_str(), 0);
}

bool Game::isMouseInRect(const glm::vec2 &top_left, const glm::vec2 &bottom_right)
{
    if (mouse_position_.x >= top_left.x && 
        mouse_position_.x <= bottom_right.x && 
        mouse_position_.y >= top_left.y &&
        mouse_position_.y <= bottom_right.y) 
        { return true; }
    return false;
}

std::string Game::loadTextFile(const std::string &file_path)
{
    std::ifstream file(file_path);
    std::string line;
    std::string text;
    while (std::getline(file, line)) {
        text += line + "\n";
    }
    return text;
}

void Game::updateMouse()
{
    mouse_buttons_ = SDL_GetMouseState(&mouse_position_.x, &mouse_position_.y);
    // 限制比例，不要出现黑边的做法
    int w, h;
    SDL_GetWindowSize(window, &w, &h);
    SDL_SetWindowAspectRatio(window, screen_size_.x/screen_size_.y, screen_size_.x/screen_size_.y);
    mouse_position_ *= screen_size_ / glm::vec2(w, h);
}

void Game::renderTexture(const Texture &texture, const glm::vec2 &position, const glm::vec2 &size, const glm::vec2 &mask)
{
    SDL_FRect src_rect = {
        texture.src_rect.x,
        texture.src_rect.y + texture.src_rect.h * (1-mask.y),
        texture.src_rect.w * mask.x,
        texture.src_rect.h * mask.y
    };
    SDL_FRect dst_rect = {
        position.x,
        position.y + size.y * (1-mask.y),
        size.x * mask.x,
        size.y * mask.y
    };
    SDL_RenderTextureRotated(renderer, texture.texture, &src_rect, &dst_rect,
                                texture.angle, 
                                nullptr, 
                                texture.is_flip ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE);
}

void Game::renderFillCircle(const glm::vec2 &position, const glm::vec2 &size, float alpha)
{
    auto texture = asset_store_->getImage("assets/UI/circle.png");
    SDL_FRect dst_rect = {
        position.x, position.y, size.x, size.y
    };
    SDL_SetTextureAlphaModFloat(texture, alpha);
    SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
}

void Game::renderHBar(const glm::vec2 &position, const glm::vec2 &size, float percent, SDL_FColor fcolor)
{
    SDL_SetRenderDrawColorFloat(renderer, fcolor.r, fcolor.g, fcolor.b, fcolor.a);
    SDL_FRect boundary_rect = {
        position.x,
        position.y,
        size.x,
        size.y
    };
    SDL_FRect fill_rect = {
        position.x,
        position.y,
        size.x * percent,
        size.y
    };
    SDL_RenderRect(renderer, &boundary_rect);
    SDL_RenderFillRect(renderer, &fill_rect);
    SDL_SetRenderDrawColorFloat(renderer, 0, 0, 0, 1);
}

void Game::drawGrid(const glm::vec2 &top_left, const glm::vec2 &bottom_right, float grid_width, SDL_FColor fcolor)
{
    SDL_SetRenderDrawColorFloat(renderer, fcolor.r, fcolor.g, fcolor.b, fcolor.a);
    for (float x = top_left.x; x <= bottom_right.x; x +=grid_width) {
        SDL_RenderLine(renderer, x, top_left.y, x, bottom_right.y);
    }
    for (float y = top_left.y; y <= bottom_right.y; y +=grid_width) {
        SDL_RenderLine(renderer, top_left.x, y, bottom_right.x, y);
    }
    SDL_SetRenderDrawColorFloat(renderer, 0, 0, 0, 1);
}

void Game::drawBoundary(const glm::vec2 &top_left, const glm::vec2 &bottom_right, float boundary_with, SDL_FColor fcolor)
{
    SDL_SetRenderDrawColorFloat(renderer, fcolor.r, fcolor.g, fcolor.b, fcolor.a);
    for(float i=0; i<boundary_with; i++) {
        SDL_FRect frect = {
            top_left.x - i,
            top_left.y - i,
            bottom_right.x - top_left.x + 2 * i,
            bottom_right.y - top_left.y + 2 * i,
        };
        SDL_RenderRect(renderer, &frect);
    }
    SDL_SetRenderDrawColorFloat(renderer, 0, 0, 0, 1);
}
